package com.wx.pay.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;


/**
* @Title: 字符工具类 
* @Package com.yotrip.common.util 
* @Description: TODO
* @author vivi
* @date 2015年12月18日 下午3:35:07 
* @version V1.0
 */
public class StringUtil {
	public final static String[] datePatterns = new String[]{
		"yyyy-MM-dd",
		"yyyy-MM",
		"yyyy",
		"yyyyMMdd",
		"yyyyMM",
		"yyyy-MM-dd HH:mm:ss",
		"yyyy-MM-dd HH:mm",
		"yyyy-MM-dd HH",
		"HH:mm:ss"
	};
	
	public final static Map<Integer, String> datePatternMap = new HashMap();
	public final static Map<Integer, SimpleDateFormat> simpleDateFormatMap = new HashMap();
	
	
	public final static SimpleDateFormat dateFormatYyyyMMddHHmmss = new SimpleDateFormat("yyyyMMddHHmmss");
	static{
		for(String pattern : datePatterns){
			datePatternMap.put(pattern.length(), pattern);
		}
		for(Entry<Integer, String> row :  datePatternMap.entrySet()){
			simpleDateFormatMap.put(row.getKey(), new SimpleDateFormat(row.getValue()));
		}
	}
	 
	/**
	 * 是否==null
	 * @param val
	 * @return
	 */
	public static boolean isNull(String val){
		return val==null;
	}
	
	/**
	 * 是否!=null
	 * @param val
	 * @return
	 */
	public static boolean isNotNull(String val){
		return val!=null;
	}
	
	/**
	 * ==null or ==""
	 * @param val
	 * @return
	 */
	public static boolean nullString(String val){
		return val==null || "".equals(val);
	}
	
	/**
	 * ==null or ==""
	 * @param val
	 * @return
	 */
	public static boolean notNullString(String val){
		return val!=null && !"".equals(val);
	}
	
	/**
	 * 转字符串
	 * @param val
	 * @return String or ""
	 */
	public static String toString(Object val){
		return val==null?"":val.toString();
	}
	
	/**
	 * 转字符串
	 * @param val
	 * @param defaultVal
	 * @return String or ""
	 */
	public static String toString(Object val, String defaultVal){
		return val==null?defaultVal:val.toString();
	}
	
	/**
	 * 转int
	 * @param val
	 * @return int or 0
	 */
	public static int toInt(String val){
		return nullString(val)?0:Integer.parseInt(val);
	}
	
	/**
	 * 转int
	 * @param val
	 * @param defaultVal
	 * @return
	 */
	public static int toInt(String val, int defaultVal){
		return nullString(val)?defaultVal:Integer.parseInt(val);
	}
	
	/**
	 * 转Integer
	 * @param val
	 * @return Integer or null
	 */
	public static int toInteger(String val){
		return nullString(val)?null:Integer.valueOf(val);
	}
	
	
	/**
	 * 转Long
	 * @param val
	 * @return Integer or null
	 */
	public static Long toLong(String val){
		return nullString(val)?null:Long.valueOf(val);
	}
	
	/**
	 * 转Long数组 
	 * @param val
	 * @return Long[] or null
	 */
	public static Long[] toLongArray(String[] vals){
		if(vals==null){
			return null;
		}
		Long[] result = new Long[vals.length];
		for(int i=0; i<vals.length ;i++){
			result[i] = Long.valueOf(vals[i]);
		}
		return result;
	}
	
	/**
	 * 转String数组 
	 * @param val
	 * @return String[] or null
	 */
	public static String[] toStringArray(Object[] vals){
		if(vals==null){
			return null;
		}
		String[] result = new String[vals.length];
		for(int i=0; i<vals.length ;i++){
			result[i] = toString(vals[i]);
		}
		return result;
	}
	
	/**
	 * 转Integer数组 
	 * @param val
	 * @return Integer[] or null
	 */
	public static Integer[] toIntegerArray(String[] vals){
		if(vals==null){
			return null;
		}
		Integer[] result = new Integer[vals.length];
		for(int i=0; i<vals.length ;i++){
			result[i] = Integer.valueOf(vals[i]);
		}
		return result;
	}
	
	/**
	 * 轮询比较获取值
	 * @param comparison 比较源字符串
	 * @param kvs 对比字符串+匹配返回字符串 对称添加，若最后一个为单数，则视为默认返回字符串
	 * @return
	 */
	public static String decode(String comparison, String... kvs){
		return decode(comparison, null, kvs);
	}
	
	/**
	 * 轮询比较获取值
	 * @param comparison 比较源字符串
	 * @param defaultVal 默认返回字符串
	 * @param kvs 对比字符串+匹配返回字符串 对称添加，若最后一个为单数，则视为默认返回字符串
	 * @return
	 */
	public static String decode(String comparison, String defaultVal, String... kvs){
		if(comparison==null || kvs==null){
			return null;
		}
		for (int i = 0; i < kvs.length; i++) {
			if(comparison.equals(kvs[i])){
				return i+2<kvs.length?kvs[i+1]:(defaultVal==null?(kvs.length%2==0?null:kvs[kvs.length-1]):defaultVal);
			}
			i++;
		}
		return null;
	}
	
	/**
	 * 转BigDecimal
	 * @param val
	 * @param defaultVal
	 * @return
	 */
	public static BigDecimal toBigDecimal(String val, BigDecimal defaultVal){
		return nullString(val)?defaultVal : new BigDecimal(val);
	}
	
	/**
	 * 转BigDecimal
	 * @param val
	 * @param defaultVal
	 * @return
	 */
	public static BigDecimal toBigDecimal(String val, double defaultVal){
		return nullString(val)?BigDecimal.valueOf(defaultVal) : new BigDecimal(val);
	}
	
	/**
	 * 转BigDecimal
	 * @param val
	 * @return 
	 */
	public static BigDecimal toBigDecimal(String val){
		return toBigDecimal(val, new BigDecimal(0));
	}
	
	/**
	 * 获取数组下标的字符
	 * @param values
	 * @param index
	 * @return
	 */
	public static String indexValue(String[] values , int index){
		return index<values.length?values[index]:null;
	}
	
	/**
	 * 获取数组下标的字符
	 * @param values
	 * @param index
	 * @param defaultVal
	 * @return
	 */
	public static String indexValue(String[] values , int index, String defaultVal){
		return index<values.length?values[index]:defaultVal;
	}
	
	/**
	 * 获取数组下标的int
	 * @param values
	 * @param index
	 * @param defaultVal
	 * @return
	 */
	public static int indexValue(String[] values , int index, int defaultVal){
		return index<values.length?toInt(values[index]):defaultVal;
	}
	
	/**
	 * 获取数组下标的int
	 * @param values
	 * @param index
	 * @param defaultVal
	 * @return
	 */
	public static int indexValueToInt(String[] values , int index, int defaultVal){
		return index<values.length?toInt(values[index]):defaultVal;
	}
	
	/**
	 * 获取数组下标的Long
	 * @param values
	 * @param index
	 * @param defaultVal
	 * @return
	 */
	public static Long indexValueToLong(String[] values , int index, Long defaultVal){
		return index<values.length?toLong(values[index]):defaultVal;
	}
	

	
	/**
	 * 获取数组下标的BigDecimal
	 * @param values
	 * @param index
	 * @param defaultVal
	 * @return
	 */
	public static BigDecimal indexValue(String[] values , int index, BigDecimal defaultVal){
		return index<values.length?toBigDecimal(values[index]):defaultVal;
	}
	
	/**
	 * 获取数组下标的BigDecimal
	 * @param values
	 * @param index
	 * @param defaultVal
	 * @return
	 */
	public static BigDecimal indexValueBigDecimal(String[] values , int index, BigDecimal defaultVal){
		return index<values.length?toBigDecimal(values[index]):defaultVal;
	}
	
	/**
	 * 转Date
	 * @param val
	 * @param pattern
	 * @return
	 */
	public static Date toDate(String val, String pattern){
		try {
			return nullString(val)?null : new SimpleDateFormat(pattern).parse(val);
		} catch (ParseException e) {
			throw new RuntimeException(e.getMessage() ,e);
		}
	}
	
	/**
	 * 转Date
	 * @param val
	 * @return
	 */
	public static Date toDate(String val){
		try {
			return nullString(val)?null : simpleDateFormatMap.get(val.length()).parse(val);
		} catch (ParseException e) {
			throw new RuntimeException(e.getMessage() ,e);
		}
	}
	
	/**
	 * 转Date
	 * @param val
	 * @param defaultVal
	 * @return
	 */
	public static Date toDate(String val, Date defaultVal){
		return nullString(val) ? defaultVal : toDate(val);
	}
	
	/**
	 * 转Date
	 * @param val
	 * @param pattern
	 * @param defaultVal
	 * @return
	 */
	public static Date toDate(String val, String pattern, Date defaultVal){
		return nullString(val) ? defaultVal : toDate(val, pattern);
	}
	
	/**
	 * in
	 * @param value
	 * @param values
	 * @return
	 */
	public static boolean in(String value, String... values){
		for(String row : values){
			if(value.equals(row)){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * map转换成url参数
	 * @param data
	 * @return
	 */
	public static String toStringForUrl(Map data){
		return toString(data, "&", "=", false);
	}
	
	/**
	 * map转换字符串
	 * @param url
	 * @param data
	 * @return
	 */
	public static String toStringForUrl(String url, Map data){
		StringBuffer result = new StringBuffer(url);
		result.append(url.indexOf("?")>-1?"&":"?");
		result.append(toString(data, "&", "=", false));
		return result.toString();
	}
	
	/**
	 * map转换字符串
	 * @param data 
	 * @param itemJoin 每一个元素的连接字符串
	 * @param kvJoin 没对键值对的连接字符串
	 * @return
	 */
	public static String toString(Map data, String itemJoin, String kvJoin){
		return toString(data, itemJoin, kvJoin, false);
	}
	
	/**
	 * map转换字符串
	 * @param data 
	 * @param itemJoin 每一个元素的连接字符串
	 * @param kvJoin 没对键值对的连接字符串
	 * @param removeNull 去除空置
	 * @return
	 */
	public static String toString(Map data, String itemJoin, String kvJoin, boolean removeNull){
		StringBuffer result = new StringBuffer();
		String m = "";
		for(Object key : data.keySet()){
			if(!removeNull || (data.get(key)!=null && !"".equals(data.get(key)))){
				result.append(m).append(key).append(kvJoin).append(data.get(key));
				m = itemJoin;
			}
		}
		return result.toString();
	}
	
	/**
	 * yyyy-MM-dd HH:mm:ss
	 * @return
	 */
	public static String nowString(){
		return simpleDateFormatMap.get(19).format(System.currentTimeMillis());
	}
	
	/**
	 * yyyyMMddHHmmss
	 * @return
	 */
	public static String nowYyyyMMddHHmmssString(){
		return dateFormatYyyyMMddHHmmss.format(System.currentTimeMillis());
	}
	
	/**
	 * yyyyMMddHHmmss
	 * @return
	 */
	public static String nowYyyyMMddHHmmssString(long addTimeMillis){
		return dateFormatYyyyMMddHHmmss.format(System.currentTimeMillis()+addTimeMillis);
	}
	
	/**
	 * xml转换成map
	 * @param xmlString
	 * @param nodeName 可为空
	 * @return
	 * @throws DocumentException
	 */
	public static Map<String, String> xmlToMap(String xmlString, String nodeName) {
		return xmlToMap(xmlString, null, nodeName);
	}
	
	/**
	 * xml转换成map
	 * @param xmlString
	 * @param class1
	 * @param nodeName
	 * @return
	 */
	public static Map<String, String> xmlToMap(String xmlString, Class<? extends Map> clazz, String nodeName){
		try {
			Document doc = DocumentHelper.parseText(xmlString);
			Element root = doc.getRootElement();
			if(notNullString(nodeName)){
				 root = root.element(nodeName);
			}
			Map<String,String> result = clazz==null?new HashMap():clazz.newInstance();
			for(Iterator item = root.elementIterator();item.hasNext();){
				Element element = (Element) item.next();
				result.put(element.getName(), element.getText());
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException("", e);
		}
	}
	
	/**
	 * xml转换成map list
	 * @param xmlString
	 * @return
	 */
	public static List<Map<String,String>> xmlToMapList(String xmlString){
		return xmlToMapList(xmlString, null, null);
	}
	
	/**
	 * xml转换成map list
	 * @param xmlString
	 * @param listNodeName
	 * @return
	 */
	public static List<Map<String,String>> xmlToMapList(String xmlString, String listNodeName){
		return xmlToMapList(xmlString, null, listNodeName);
	}
	
	/**
	 * xml转换成map list
	 * @param xmlString
	 * @param listNodeName
	 * @return
	 */
	public static List<Map<String,String>> xmlToMapList(String xmlString,int level, String listNodeName){
		return xmlToMapList(xmlString, null,level, listNodeName);
	}
	
	/**
	 * xml转换成map list
	 * @param xmlString
	 * @param clazz
	 * @param listNodeName
	 * @return
	 */
	public static List<Map<String,String>> xmlToMapList(String xmlString, Class<? extends Map> clazz, String listNodeName){
		List<Map<String,String>> result = new ArrayList();
		try {
			Document doc = DocumentHelper.parseText(xmlString);
			Element rows = doc.getRootElement();
			if(notNullString(listNodeName)){
				rows = rows.element(listNodeName);
			}
			for(Iterator item = rows.elementIterator(); item.hasNext();){
				Map<String,String> row = clazz==null?new HashMap():clazz.newInstance();
				Element element = (Element) item.next();
				for(Iterator item2 = element.elementIterator(); item2.hasNext();){
					Element e = (Element) item2.next();
					row.put(e.getName(), e.getText());
				}
				result.add(row);
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException("", e);
		}
	}
	
	/**
	 * xml转换成map list
	 * @param xmlString
	 * @param clazz
	 * @param listNodeName
	 * @return
	 */
	public static List<Map<String,String>> xmlToMapList(String xmlString, Class<? extends Map> clazz,int level, String listNodeName){
		List<Map<String,String>> result = new ArrayList();
		try {
			Document doc = DocumentHelper.parseText(xmlString);
			Element rows = doc.getRootElement();
			if(notNullString(listNodeName)){
				level--; //将级别设定到父级别
				if(level > 1)
					for(int i = 1;i < level; i++)  
						rows = (Element) rows.elements().get(0);
				rows = rows.element(listNodeName);
			}
			for(Iterator item = rows.elementIterator(); item.hasNext();){
				Map<String,String> row = clazz==null?new HashMap():clazz.newInstance();
				Element element = (Element) item.next();
				for(Iterator item2 = element.elementIterator(); item2.hasNext();){
					Element e = (Element) item2.next();
					row.put(e.getName(), e.getText());
				}
				result.add(row);
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException("", e);
		}
	}
	
	/**
	 * xml转Map(无级)
	 * @param xmlString
	 * @return
	 */
	public static Map<String,Object> xml2Map(String xmlString){
		Map<String,Object> result = new LinkedHashMap();
		try {
			Document doc = DocumentHelper.parseText(xmlString);
			Element root = doc.getRootElement();
			xml2MapLoadData(root, result);
		} catch (DocumentException e) {
			throw new RuntimeException("", e);
		}
		return result; 
	}
	
	/**
	 * xml转Map加载节点数据(递归)
	 * @param element
	 * @param data
	 */
	public static void xml2MapLoadData(Element element, Map<String,Object> data){
		if(element.isTextOnly()){
			data.put(element.getName(), element.getText());
		}else{
			Map attr = xml2MapLoadAttr(element);
			data.put("@", attr);
			Map data2 = new LinkedHashMap();
			for(Iterator item = element.elementIterator(); item.hasNext();){
				Element row = (Element) item.next();
				xml2MapLoadData(row, data2);
			}
			if(data.get(element.getName())!=null){
				if(data.get(element.getName()) instanceof List){
					((List)data.get(element.getName())).add(data2);
				}else{
					List list = new ArrayList();
					list.add(data.remove(element.getName()));
					list.add(data2);
					data.put(element.getName(), list);
				}
			}else{
				data.put(element.getName(), data2);
			}
		}
	}
	
	/**
	 * 加载节点属性
	 * @param element
	 * @return
	 */
	public static Map<String, String> xml2MapLoadAttr(Element element){
		List<Attribute> attrs = element.attributes();
		if(attrs==null || attrs.size()==0){
			return null;
		}
		Map<String, String> result = new LinkedHashMap<String, String>(attrs.size());
		for(Attribute attr : attrs){
			result.put(attr.getName(), attr.getValue());
		}
		return result;
	}
	
	
	/**
	 * 读取流中的字符串
	 * @param in
	 * @return
	 * @throws IOException
	 */
	public static String readString(InputStream in) throws IOException{
		if(in==null){
			return null;
		}
		StringBuffer result = new StringBuffer();
		InputStreamReader isr = null;
		BufferedReader br = null;
		String row = null;
		try {
			isr = new InputStreamReader(in, "UTF-8");
			br = new BufferedReader(isr);
			while((row=br.readLine())!=null){
				result.append(row);
			}
		} catch (IOException e) {
			throw e;
		}finally{
			if(isr!=null){
				isr.close();
			}
			if(br!=null){
				br.close();
			}
		}
		return result.toString();
	}
	
	/**
	 * 转换成xml
	 * @param data
	 * @param rootNodeName
	 * @return
	 */
	public static String toXml(Map<String,String> data, String rootNodeName){
		StringBuffer params = new StringBuffer();
		if(rootNodeName!=null){
			params.append("<").append(rootNodeName).append(">");
		}
		for(Entry<String, String> param : data.entrySet()){
			params.append("<").append(param.getKey()).append(">")
			.append(param.getValue())
			.append("</").append(param.getKey()).append(">");
		}
		if(rootNodeName!=null){
			params.append("</").append(rootNodeName).append(">");
		}
		return params.toString();
	}
	
	/**
	 * url编码(UTF-8)
	 * @param s
	 * @return
	 */
	public static String urlEncode(String s){
		return urlEncode(s, "UTF-8");
	}
	
	
	/**
	 * url编码
	 * @param s
	 * @param enc
	 * @return
	 */
	public static String urlEncode(String s, String enc){
		try {
			return URLEncoder.encode(s, enc);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * url解码
	 * @param s
	 * @param enc
	 * @return
	 */
	public static String urlDecode(String s, String enc){
		try {
			return URLDecoder.decode(s, enc);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	/**
	 * url解码(UTF-8)
	 * @param s
	 * @return
	 */
	public static String urlDecode(String s){
		return urlDecode(s, "UTF-8");
	}
	
}

